supportedOrientations(LANDSCAPE_RIGHT)
function setup()
numParticles = 120
particles = {}
radius = 8

circle1 = physics.body(CIRCLE, 100)
circle1.x,circle1.y = 500,300
rect1 = physics.body(POLYGON, vec2(100,200), vec2(400,200), vec2(300,290), vec2(200,290))
edges = physics.body(CHAIN, false, vec2(0,0), vec2(WIDTH/4,80), vec2(WIDTH/2,30), vec2(WIDTH * 0.7,120), vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT), vec2(0,0))
circle1.type = STATIC
rect1.type = STATIC
edges.type = STATIC

for i = 1,numParticles do
local particle = physics.body(CIRCLE, radius + math.random())
particle.x = math.random(100,WIDTH - 100)
particle.y = math.random(500,HEIGHT - 100)
particle.restitution = 0
particle.friction = 0
particle.fixedRotation = true
particle.sleepingAllowed = false
particle.interpolate = true
particles[i] = particle
end
parameter.boolean("thresholded",true)
parameter.number("threshold",0,1.0,0.7)
parameter.boolean("drawParticle",false)
parameter.boolean("drawImg",false)
parameter.boolean("paused",false)
parameter.watch("1/DeltaTime")

falloffImg = createFalloffImg()

ballSize = 220
ballMesh = mesh()
ballMesh.shader = shader(metaballShader.vertexShader, metaballShader.fragmentShader)
ballMesh:addRect(0, 0, ballSize, ballSize)
ballMesh:setRectTex(1,0,0,1,1)
ballMesh.texture = falloffImg
firstPass = image(WIDTH,HEIGHT)
secondPass = mesh()
secondPass:addRect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
secondPass:setRectTex(1,0,0,1,1)
secondPass.texture = firstPass
secondPass.shader = shader(thresholdShader.vertexShader, thresholdShader.fragmentShader)
secondPass.shader.color = color(161, 203, 223, 255)
end

function draw()
if paused then
physics.pause()
else
physics.gravity(Gravity * 2)
physics.resume()
end
if drawImg then
background(0, 0, 0, 255)
sprite(falloffImg,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
return
end
if thresholded then
setContext(firstPass) 
end
background(0, 0, 0, 255)
for i = 1,numParticles do
local particle = particles[i]
translate(particle.x,particle.y)
ballMesh:draw()
resetMatrix()
end
if drawParticle then
for i = 1,numParticles do
drawBody(particles[i])
end
end
if thresholded then
setContext()
background(0)
secondPass.shader.threshold = threshold
secondPass:draw()
end
drawBody(edges)
drawBody(rect1)
drawBody(circle1)
end

function touched(touch)
if touch.state == BEGAN then

end
end

--create a texture for the falloff curve
function createFalloffImg()
local w = 80
local img = image(w * 2,w * 2)
local r = 8
setContext(img)
background(0, 0, 0, 255)
for i = w,1,-1 do
local f = (r / i) ^ 2
fill(255 * f, 255)
ellipse(w,w,i * 2)
end
setContext()
return img
end

function drawBody(body)
pushStyle()
pushMatrix()

strokeWidth(5)
stroke(148, 224, 135, 255)
fill(0, 0, 0, 0)
translate(body.x, body.y)
rotate(body.angle)

if body.shapeType == POLYGON then
strokeWidth(3.0)
local points = body.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CHAIN or body.shapeType == EDGE then
strokeWidth(3.0)
local points = body.points
for j = 1,#points-1 do
a = points[j]
b = points[j+1]
line(a.x, a.y, b.x, b.y)
end
elseif body.shapeType == CIRCLE then
strokeWidth(3.0)
--line(0,0,body.radius-3,0)
ellipse(0,0,body.radius*2)
end
popMatrix()
popStyle()
end

metaballShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec2 texCoord;
varying highp vec2 vTexCoord;
void main()
{
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
#extension GL_EXT_shader_framebuffer_fetch : require
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col = gl_LastFragData[0];

col.xyz += texture2D( texture, vTexCoord ).xyz;
col.a = 1.0;
//Set the output color to the texture color
gl_FragColor = col;
}
]] }

thresholdShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec2 texCoord;
varying highp vec2 vTexCoord;
void main()
{
//Pass the mesh color to the fragment shader
vTexCoord = texCoord;

//Multiply the vertex position by our combined transform
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;
uniform lowp float threshold;
uniform lowp vec4 color;
//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
//Sample the texture at the interpolated coordinate
lowp vec4 col = texture2D( texture, vTexCoord );

if (col.r < threshold) {
col = vec4(0.0,0.0,0.0,0.0);
}
else {
col = color;
}

//Set the output color to the texture color
gl_FragColor = col;
}
]] }